#ifndef __WX_MENUUTILS_H__
#define __WX_MENUUTILS_H__

#ifdef __GNUG__
#pragma interface "menuutils.h"
#endif

#include "wx/panel.h"
#include "wx/dialog.h"
#include "wx/listbox.h"
#include "wx/treectrl.h"
#include "wx/string.h"
#include "keybinder.h"

int wxFindMenuItem( wxMenuBar *, const wxString &strMenuItemName );
int FindMenuDuplicateItems( wxMenu* pMenu, wxString& rStr, int& rCount );
wxString GetFullMenuPath( int );

#define wxSAFE_DELETE(x)          { if (x) delete x; x = NULL; }
#define wxSAFE_DELETE_ARRAY(x)        { if (x) delete [] x; x = NULL; }
#define wxMENUCMD_TYPE            0x1234

class wxMenuCmd : public wxCmd {
    wxMenuItem *m_pItem;
  public:
    static wxMenuBar *m_pMenuBar;
    static void SetMenuBar( wxMenuBar *p ) { m_pMenuBar = p; }
    static void Register( wxMenuBar *p ) {
      wxCmd::AddCmdType( wxMENUCMD_TYPE, wxMenuCmd::CreateNew );
      wxMenuCmd::SetMenuBar( p );
    }
    static wxCmd *CreateNew( wxString cmdName, int id );
  public:
    wxMenuCmd( wxMenuItem *p, const wxKeyBind &first,
               const wxString &name = wxEmptyString,
               const wxString &desc = wxEmptyString ) :
      wxCmd( first, p->GetId(), name, desc ), m_pItem( p ) {;}

    wxMenuCmd( wxMenuItem *p = NULL, const wxString &name = wxEmptyString,
               const wxString &desc = wxEmptyString ) {
      m_pItem = p;
      m_strDescription = desc;
      m_strName = name;
      if( m_pItem ) {
        m_nId = m_pItem->GetId();
      }
    }
    virtual ~wxMenuCmd() {}
  public:
    virtual void DeepCopy( const wxCmd *p ) {
      wxMenuCmd *m = ( wxMenuCmd * )p;
      m_pItem = m->m_pItem;
      wxCmd::DeepCopy( p );
    }
    virtual wxCmd *Clone() const {
      wxCmd *ret = new wxMenuCmd();
      ret->DeepCopy( this );
      return ret;
    }
    virtual int GetType() const {
      return wxMENUCMD_TYPE;
    }
    static bool IsNumericMenuItem( wxMenuItem* pwxMenuItem );
  protected:
    void Exec( wxObject *origin, wxEvtHandler *client );
    void Update( wxMenuItem* pMnuItem = 0 );
};

class wxMenuWalker {
  protected:
    int m_nLevel;
  public:
    wxMenuWalker() { m_nLevel = 0; }
    virtual ~wxMenuWalker() {}
  protected:
    void Walk( wxMenuBar *p, void *data );
    void WalkMenu( wxMenuBar *p, wxMenu *, void * );
    void WalkMenuItem( wxMenuBar *p, wxMenuItem *, void * );
    virtual void *OnMenuWalk( wxMenuBar *p, wxMenu *m, void *data ) = 0;
    virtual void *OnMenuItemWalk( wxMenuBar *p, wxMenuItem *m, void *data ) = 0;
    virtual void OnMenuExit( wxMenuBar *, wxMenu *, void * ) {}
    virtual void DeleteData( void *data ) = 0;
    bool IsNumericMenuItem( wxMenuItem* pwxMenuItem );
};

class wxExTreeItemData : public wxTreeItemData {
  protected:
    int m_nMenuId;
  public:
    wxExTreeItemData( int id = wxID_INVALID ) : m_nMenuId( id ) {}
    virtual ~wxExTreeItemData() {}
    void SetMenuItemId( int n ) {
      m_nMenuId = n;
    }
    int GetMenuItemId() {
      return m_nMenuId;
    }
};

class wxMenuTreeWalker : public wxMenuWalker {
    wxTreeCtrl *m_pTreeCtrl;
    wxTreeItemId m_root;
  public:
    wxMenuTreeWalker() {}
    virtual ~wxMenuTreeWalker() {}
    void FillTreeBranch( wxMenuBar *p, wxTreeCtrl *ctrl, wxTreeItemId branch );
    void FillTreeCtrl( wxMenuBar *p, wxTreeCtrl *ctrl, const wxString &rootname = wxT( "root" ) ) {
      ctrl->DeleteAllItems();
      FillTreeBranch( p, ctrl, ctrl->AddRoot( rootname ) );
    }
  protected:
    void *OnMenuWalk( wxMenuBar *p, wxMenu *, void * );
    void *OnMenuItemWalk( wxMenuBar *p, wxMenuItem *, void * );
    void DeleteData( void *data );
};

class wxExComboItemData : public wxClientData {
  protected:
    wxArrayString m_arrStr;
    wxArrayLong m_arrID;
  public:
    wxExComboItemData() {}
    virtual ~wxExComboItemData() {}
    int GetID( int n ) const { return m_arrID[n]; }
    wxArrayString &GetCmdNameArr() { return m_arrStr; }
    void Append( const wxString &name, int id ) { m_arrStr.Add( name ); m_arrID.Add( id ); }
    void SetID( int n, int id ) { m_arrID[n] = id; }
};

class wxMenuComboListWalker : public wxMenuWalker {
    wxComboBox *m_pCategories;
    wxString m_strAcc;
  public:
    wxMenuComboListWalker() {}
    virtual ~wxMenuComboListWalker() {}
    void FillComboListCtrl( wxMenuBar *p, wxComboBox *combo );
  protected:
    void *OnMenuWalk( wxMenuBar *p, wxMenu *, void * );
    void *OnMenuItemWalk( wxMenuBar *p, wxMenuItem *, void * );
    void OnMenuExit( wxMenuBar *p, wxMenu *m, void *data );
    void DeleteData( void *data );
};

class wxMenuShortcutWalker : public wxMenuWalker {
    wxCmdArray *m_pArr;
  public:
    wxMenuShortcutWalker() {}
    virtual ~wxMenuShortcutWalker() {}
    void ImportMenuBarCmd( wxMenuBar *p, wxCmdArray *arr ) {
      m_pArr = arr;
      Walk( p, NULL );
    }
  protected:
    void *OnMenuWalk( wxMenuBar *, wxMenu *, void * ) { return NULL; }
    void *OnMenuItemWalk( wxMenuBar *p, wxMenuItem *, void * );
    void DeleteData( void *data );
};

#endif
